package com.leantech.android.browser.ui.search

import android.annotation.SuppressLint
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import androidx.core.widget.doOnTextChanged
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.ConcatAdapter
import androidx.recyclerview.widget.LinearLayoutManager
import com.cscj.android.repository.db.entity.HotSearchEntity
import com.cscj.android.repository.db.entity.SearchHistoryEntity
import com.cscj.android.utils.LOG
import com.google.android.material.snackbar.Snackbar
import com.leantech.android.browser.R
import com.leantech.android.browser.browser.BrowserDelegate
import com.leantech.android.browser.databinding.FragmentSearchBinding
import com.leantech.android.browser.dialog.BottomSheetDialogHelper
import com.leantech.android.browser.ui.InterstitialAdViewModel
import com.leantech.android.browser.ui.browser.BrowserActivity
import com.leantech.android.browser.ui.browser.viewmodel.BrowserTabViewModel
import com.leantech.android.browser.ui.browser.viewmodel.BrowserViewModel
import com.leantech.android.browser.ui.search.adapter.CurrentUrlAdapter
import com.leantech.android.browser.ui.search.adapter.SearchClipboardAdapter
import com.leantech.android.browser.ui.search.adapter.SearchHistorySectionAdapter
import com.leantech.android.browser.ui.search.adapter.SearchRecommendAdapter
import com.leantech.android.browser.ui.search.adapter.SearchRecommendSectionAdapter
import com.leantech.android.browser.utils.clearClipboard
import com.leantech.android.browser.utils.copyToClipboard
import com.leantech.android.browser.utils.getClipboardText
import com.leantech.android.browser.utils.onThrottleClick
import com.leantech.android.browser.utils.show
import com.leantech.android.browser.utils.toast
import com.qmuiteam.qmui.util.QMUIKeyboardHelper
import com.qmuiteam.qmui.widget.dialog.QMUIBottomSheet
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import org.koin.androidx.viewmodel.ext.android.activityViewModel
import org.koin.androidx.viewmodel.ext.android.viewModel
import splitties.fragmentargs.arg
import splitties.fragments.start
import splitties.resources.color


class SearchFragment : Fragment(), QMUIBottomSheet.BottomListSheetBuilder.OnSheetItemClickListener,
    SearchHistorySectionAdapter.SearchHistorySectionAdapterCallback,
    SearchRecommendAdapter.SearchRecommendItemAdapterCallback,
    CurrentUrlAdapter.CurrentUrlCallback {

    private var searchKeyword: String by arg()
    private var fromHome: Boolean by arg()

    private lateinit var binding: FragmentSearchBinding

    private lateinit var currentUrlAdapter: CurrentUrlAdapter
    private lateinit var searchClipboardAdapter: SearchClipboardAdapter
    private lateinit var searchHistorySectionAdapter: SearchHistorySectionAdapter
    private lateinit var searchRecommendSectionAdapter: SearchRecommendSectionAdapter

    private lateinit var concatAdapter: ConcatAdapter


    private val viewModel by viewModel<SearchViewModel>()

    private val adViewModel by activityViewModel<InterstitialAdViewModel>()
    private lateinit var browserDelegate: BrowserDelegate

    private lateinit var editSnackbar: Snackbar

    private val browserViewModel by activityViewModel<BrowserViewModel>()

    private val browserTabViewModel by activityViewModel<BrowserTabViewModel>()


    companion object {

        fun newInstance(keyword: String = "", fromHome: Boolean = false): SearchFragment {
            return SearchFragment().apply {
                searchKeyword = keyword
                this.fromHome = fromHome
            }
        }
    }

    override fun onAttach(context: Context) {
        super.onAttach(context)
        if (context is BrowserDelegate) {
            browserDelegate = context
        } else {
            throw IllegalStateException("activity must implement BrowserDelegate")
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
    ): View {
        binding = FragmentSearchBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initView()
        subscribeFlow()
    }

    private fun subscribeFlow() {
        viewLifecycleOwner.lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                launch {
                    viewModel.searchHistoryFlow.collectLatest {
                        searchHistorySectionAdapter.submitList(it)
                        if (it.isEmpty()) {
                            dismissSnackbar()
                        }
                    }
                }

                launch {
                    viewModel.currentSearchEngineFlow.collectLatest { currentEngine ->
                        currentEngine?.apply {
                            binding.imageSearchEngine.setImageResource(
                                BottomSheetDialogHelper.getSearchEngineIcon(
                                    id
                                )
                            )
                        }
                    }
                }

                launch {
                    viewModel.searchRecommendFlow.collectLatest {
                        searchRecommendSectionAdapter.submitList(it)
                    }
                }

                launch {
                    browserTabViewModel.currentUrlFlow.collectLatest { (title, url) ->
                        if (!fromHome) {
                            concatAdapter.removeAdapter(searchClipboardAdapter)
                            concatAdapter.addAdapter(0, currentUrlAdapter)
                            currentUrlAdapter.updateContent(title, url)
                        }
                    }
                }

            }
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    private fun initView() {
        binding.editSearch.setText(searchKeyword)
        binding.editSearch.doOnTextChanged { _, _, _, _ ->
            updateSearchState()
            //TODO 展示搜索建议
        }

        updateSearchState()

        binding.editSearch.requestFocus()
        QMUIKeyboardHelper.showKeyboard(binding.editSearch, 300)

        binding.btnSearch.onThrottleClick {
            val textLength = binding.editSearch.text?.length ?: 0
            if (textLength > 0) {
                search()
            } else {
                parentFragmentManager.popBackStackImmediate()
            }
        }

        binding.root.findViewById<View>(R.id.back_any)?.onThrottleClick {
            parentFragmentManager.popBackStackImmediate()
        }

        binding.editSearch.setOnEditorActionListener { _, actionId, _ ->
            if (actionId == EditorInfo.IME_ACTION_SEARCH) {
                search()
                true
            } else false
        }

        binding.imageSearchEngine.onThrottleClick {

            BottomSheetDialogHelper.createSearchEngineDialog(
                requireContext(),
                viewModel.getSearchEngines(),
                onItemClick = { se ->
                    if (se != null) {
                        viewModel.switchEngine(se.id)
                    }
                }) {

            }.show()
        }


        currentUrlAdapter = CurrentUrlAdapter(this)
        searchClipboardAdapter = SearchClipboardAdapter(callback = searchClipboardCallback)
        searchHistorySectionAdapter = SearchHistorySectionAdapter(this)
        searchRecommendSectionAdapter = SearchRecommendSectionAdapter(this)

        concatAdapter = ConcatAdapter(searchHistorySectionAdapter, searchRecommendSectionAdapter)

        binding.recyclerView.layoutManager = LinearLayoutManager(requireContext())
        binding.recyclerView.adapter = concatAdapter

    }

    private fun search(keyword: String = "") {
        val text = if (keyword.isNotEmpty()) keyword else binding.editSearch.text?.toString()
        if (text.isNullOrBlank()) {
            binding.editSearch.text?.clear()
        } else {
            if (!browserViewModel.currentPrivacyMode()) {
                viewModel.saveSearchHistory(text)
            }
            //
            searchWithKeywords(text)
        }
    }

    private fun updateSearchState() {
        val textLength = binding.editSearch.text?.length ?: 0
        val res =
            if (textLength > 0) R.drawable.icon_search_cancel else R.drawable.icon_refresh_small
        binding.btnRefresh.show(textLength > 0)
        binding.btnRefresh.setImageResource(res)
        binding.btnSearch.setText(if (textLength > 0) R.string.text_search else R.string.cancel)
        binding.btnRefresh.onThrottleClick {
            if (textLength > 0) {
                binding.editSearch.text?.clear()
            } else {
                //refresh
                browserDelegate.refresh()
            }
        }
    }

    override fun onClick(dialog: QMUIBottomSheet, itemView: View, position: Int, tag: String?) {
        dialog.dismiss()
        if (tag == BottomSheetDialogHelper.TagCustomEngine) {

        } else if (tag?.toIntOrNull() != null) {
            val id = tag.toInt()
            viewModel.switchEngine(id)
        }
    }


    /**
     * 点击剪切板链接跳转到搜索
     */
    private val searchClipboardCallback = object : SearchClipboardAdapter.SearchClipboardCallback {

        override fun onClipItemClicked(clipContent: CharSequence?) {
            clipContent?.also { url ->
                searchWithKeywords(url.toString())
            }
            clearClipboard()
        }
    }


    private fun searchWithKeywords(query: String) {
        start<BrowserActivity> {
            action = BrowserActivity.InternalActionSearch
            putExtra(BrowserActivity.ExtraSearchKeyword, query)
            putExtra(BrowserActivity.ExtraSearchOpenNewTab, false)
            putExtra(BrowserActivity.ExtraSearchClearHistory, fromHome)
        }

        //每次搜索都加载广告
        adViewModel.requestLoadAd()
    }

    override fun onResume() {
        super.onResume()
        ensureClipboard()
    }

    private fun ensureClipboard() {
        if (!::searchClipboardAdapter.isInitialized) return
        if (!fromHome) return //优先级比当前网页Url要低

        LOG.d("SearchFragment", "onPrimaryClipChanged")
        val content = getClipboardText()
        if (content.isBlank()) {
            concatAdapter.removeAdapter(searchClipboardAdapter)
        } else {
            concatAdapter.addAdapter(0, searchClipboardAdapter)
            searchClipboardAdapter.updateContent(content)
        }
    }

    override fun onAllHistoryRemoved() {
        viewModel.deleteAllSearchHistory()
    }

    override fun onEnterEditMode() {
        QMUIKeyboardHelper.hideKeyboard(binding.editSearch)
        searchHistorySectionAdapter.toggleEditMode(true)
        editSnackbar = Snackbar.make(
            binding.recyclerView,
            "已进入编辑模式，可点击图标右上角的图标进行删除",
            Snackbar.LENGTH_INDEFINITE
        ).setAction("退出编辑") {
            searchHistorySectionAdapter.toggleEditMode(false)
        }.setTextColor(color(R.color.white))
            .setActionTextColor(color(R.color.transparentWhite60))

        editSnackbar.show()
    }

    override fun onCompleteClick() {
        searchHistorySectionAdapter.toggleEditMode(false)
    }

    private fun dismissSnackbar() {
        if (::editSnackbar.isInitialized) {
            editSnackbar.dismiss()
        }
    }

    override fun onHistoryItemClicked(searchKeywords: String) {
        if (!searchHistorySectionAdapter.isEditMode()) {
            search(searchKeywords)
        }
    }

    override fun onHistoryItemRemoved(item: SearchHistoryEntity, adapterPosition: Int) {
        viewModel.deleteSearchHistory(item)
    }

    override fun onSearchRecommendItemClicked(data: HotSearchEntity) {
        searchWithKeywords(data.url)
    }

    override fun onDestroyView() {
        super.onDestroyView()
        dismissSnackbar()
    }

    override fun onCopyClicked(url: String) {
        copyToClipboard(url)
        toast("已复制到粘贴板")
    }
}